﻿using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

public class PrefabTool : EditorWindow
{
    Vector2 scrollPos = Vector2.zero;
    string path;
    string Path
    {
        get
        {
            return path;
        }
        set
        {
            if (value != path)
            {
                if (directoryPrefabs == null)
                {
                    directoryPrefabs = new List<string>();
                }
                else
                {
                    directoryPrefabs.Clear();
                }
                if (AllAssetPaths == null)
                {
                    AllAssetPaths = new List<string>();
                }
                else
                {
                    AllAssetPaths.Clear();
                }
                path = value;
            }
        }
    }

    static EditorWindow myWindow;
    static List<string> directoryPrefabs;
    static List<string> AllAssetPaths;

    bool showPrefabs = true;

    string prefabName = "";
    string generatePath = "Assets/Prefab";

    int replaceModeIndex = -1;
    int ReplaceModeIndex
    {
        get
        {
            return replaceModeIndex;
        }
        set
        {
            if (value != replaceModeIndex)
            {
                if (directoryPrefabs == null)
                {
                    directoryPrefabs = new List<string>();
                }
                else
                {
                    directoryPrefabs.Clear();
                }
                if (AllAssetPaths == null)
                {
                    AllAssetPaths = new List<string>();
                }
                else
                {
                    AllAssetPaths.Clear();
                }
                Path = "";
                replaceModeIndex = value;
            }
        }
    }
    [MenuItem("WBTools/ExportGuestModel")]
    static void Init()
    {
        myWindow = EditorWindow.GetWindow(typeof(PrefabTool));
        directoryPrefabs = new List<string>();
        AllAssetPaths = new List<string>();
        myWindow.minSize = new Vector2(500, 300);
    }

    void OnGUI()
    {
        GetPath();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("prefab名称:", GUILayout.Width(100));
        prefabName = GUILayout.TextField(prefabName);
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("生成prefab路径:", GUILayout.Width(100));
        generatePath = GUILayout.TextField(generatePath);
        if (GUILayout.Button("选择", GUILayout.Width(50)))
        {
            generatePath = EditorUtility.OpenFolderPanel("选择生成prefab路径", Application.dataPath, "");
        }
        EditorGUILayout.EndHorizontal();
        Event e = Event.current;
        if (Event.current.type == EventType.DragExited || Event.current.type == EventType.DragUpdated)
        {
            if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.Link;
                if (Event.current.type == EventType.DragExited)
                {
                    DragAndDrop.AcceptDrag();
                    if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
                    {
                        if (File.Exists(DragAndDrop.paths[0]))
                        {
                            EditorUtility.DisplayDialog("警告", "请拖拽文件夹！", "确定");
                            return;
                        }
                        generatePath = DragAndDrop.paths[0];
                    }
                }
                e.Use();
            }
            else
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
            }
        }

        ReplaceModeIndex = 0;

        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

        ShowAllPrefabs();
        EditorGUILayout.EndScrollView();
        EditorGUILayout.BeginHorizontal();
        LoadFBX();
        EditorGUILayout.EndHorizontal();
        GeneratePrefab();

    }
    void GetPath()
    {
        Event e = Event.current;
        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("资源文件夹:(拖拽)", GUILayout.Width(100));
        Path = GUILayout.TextField(Path);
        if (GUILayout.Button("选择", GUILayout.Width(50)))
        {
            Path = EditorUtility.OpenFolderPanel("选择路径", Application.dataPath, "");
        }
        EditorGUILayout.EndHorizontal();
        if (Event.current.type == EventType.DragExited || Event.current.type == EventType.DragUpdated)
        {
            if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.Link;
                if (Event.current.type == EventType.DragExited)
                {
                    DragAndDrop.AcceptDrag();
                    if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
                    {
                        if (File.Exists(DragAndDrop.paths[0]))
                        {
                            EditorUtility.DisplayDialog("警告", "请拖拽文件夹！", "确定");
                            return;
                        }
                        Path = DragAndDrop.paths[0];
                    }
                }
                e.Use();
            }
            else
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
            }
        }
    }
    void ShowAllPrefabs()
    {
        if (directoryPrefabs != null && directoryPrefabs.Count > 0)
        {
            showPrefabs = EditorGUILayout.Foldout(showPrefabs, "显示动画资源");
            if (showPrefabs)
            {
                for (int i = 0; i < directoryPrefabs.Count; i++)
                {
                    int index = i;
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.SelectableLabel($"FBX路径：{directoryPrefabs[index]}");
                    if (GUILayout.Button("查看", GUILayout.Width(60)))
                    {
                        EditorGUIUtility.PingObject(AssetDatabase.LoadAssetAtPath<Object>(directoryPrefabs[index]));
                        Selection.activeGameObject = AssetDatabase.LoadAssetAtPath<Object>(directoryPrefabs[index]) as GameObject;
                    }
                    if (GUILayout.Button("删除", GUILayout.Width(60)))
                    {
                        directoryPrefabs.RemoveAt(index);
                    }
                    EditorGUILayout.EndHorizontal();
                }
            }
            else
            {
                if (GUILayout.Button("清空选择", GUILayout.Width(60)))
                {
                    directoryPrefabs.Clear();
                    AllAssetPaths.Clear();
                    Path = "";
                }
            }
        }
    }

    void GeneratePrefab()
    {
        if (GUILayout.Button("生成预制体"))
        {
            if (string.IsNullOrEmpty(prefabName))
            {
                Debug.LogError("请填写prefabName名称");
                return;
            }
            AllAssetPaths.Clear();
            if (directoryPrefabs != null)
            {
                directoryPrefabs.Clear();
            }
            else
            {
                directoryPrefabs = new List<string>();
            }
            LoadFBXAuto();

            if (Directory.Exists(generatePath))
            {
                Debug.Log("开始生成");

                string rootFbxPath = string.Empty;
                string texturePath = string.Empty;
                string matPath = string.Empty;

                if (directoryPrefabs.Count > 0)
                {
                    //找出fbx根结点
                    foreach (var fbxPath in directoryPrefabs)
                    {
                        string fbxName = System.IO.Path.GetFileNameWithoutExtension(fbxPath);
                        string fbxNmaeE = System.IO.Path.GetFileName(fbxPath);
                        Debug.Log("fbx名字" + fbxName);
                        if (fbxName.Contains("@"))//动作
                        {
                            if (!AllAssetPaths.Contains(fbxPath))
                                AllAssetPaths.Add(fbxPath);
                        }
                        else //根节点
                        {
                            rootFbxPath = fbxPath;
                            texturePath = fbxPath.Replace(fbxNmaeE, fbxName + "_d.png");
                            matPath = fbxPath.Replace(fbxNmaeE, fbxName + "_M.mat");
                        }
                    }
                }

                GameObject rootFbx = AssetDatabase.LoadAssetAtPath<Object>(rootFbxPath) as GameObject;

                if (rootFbx != null)
                {
                    GameObject prefab = new GameObject(prefabName);
                    prefab.AddComponent<CitySpaceManTrigger>();
                    prefab.AddComponent<LWBattleRVOAgent>();

                    GameObject gobj = PrefabUtility.InstantiatePrefab(rootFbx, prefab.transform) as GameObject;
                    //获取材质，不存在就创建
                    Material mat = AssetDatabase.LoadAssetAtPath(matPath, typeof(Material)) as Material;
                    if (mat == null)
                    {
                        mat = new Material(Shader.Find("WB/WB_Character"));
                        Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath);
                        mat.mainTexture = tex;
                        AssetDatabase.CreateAsset(mat, matPath);
                    }

                    //更换材质
                    SkinnedMeshRenderer[] skinArr = gobj.GetComponentsInChildren<SkinnedMeshRenderer>(true);
                    for (int i = 0; i < skinArr.Length; i++)
                    {
                        skinArr[i].material = mat;
                    }

                    //测试代码，不存在就添加
                    //if (skinArr.Length == 0)
                    //{
                    //    SkinnedMeshRenderer smr = gobj.AddComponent<SkinnedMeshRenderer>();
                    //    smr.material = mat;
                    //}
                    //脚本相关，关联动画clip
                    SimpleAnimation simple = gobj.AddComponent<SimpleAnimation>();

                    List<SimpleAnimation.EditorState> list = new List<SimpleAnimation.EditorState>();

                    for (int i = 0; i < AllAssetPaths.Count; i++)
                    {
                        AnimationClip clip = AssetDatabase.LoadAssetAtPath(AllAssetPaths[i], typeof(AnimationClip)) as AnimationClip;
                        if (clip != null)
                        {
                            string clipName = clip.name;
                            if (clipName == "idel")
                            {
                                simple.SetDefaultClip(clip);
                            }
                            else if (clipName == "attack1")
                            {
                                list.Add(GetState(clip, "attack"));
                            }
                            else
                            {
                                list.Add(GetState(clip, clipName));
                                if (clipName == "run")
                                {
                                    list.Add(GetState(clip, "walk"));
                                }
                                if (clipName == "attack_skill")
                                {
                                    list.Add(GetState(clip, "attack_move"));
                                }
                                //测试
                                //if (clipName == "Run01")
                                //{
                                //    list.Add(GetState(clip, "myrun"));
                                //}
                            }
                        }
                        else
                        {
                            Debug.LogError("未加载到clip" + AllAssetPaths[i]);
                        }
                    }
                    simple.SetEditorStates(list.ToArray());

                    //添加其他字节点
                    GetPoint(prefab, "FirePoint");
                    GetPoint(prefab, "Point_Tip_Sit");
                    GetPoint(prefab, "Point_Tip_Stand");

                    string path = string.Format("{0}/{1}.prefab", generatePath, prefabName);

                    PrefabUtility.SaveAsPrefabAsset(prefab, path, out bool success);
                    if (!success)
                    {
                        Debug.LogError($"预制体：{path} 保存失败!");
                    }
                    else
                    {
                        Debug.Log($"预制体：{path} 保存成功!");
                    }
                    GameObject.DestroyImmediate(prefab);
                }
                else
                {
                    Debug.LogError("加载失败" + rootFbxPath);
                }
            }
            else
            {
                Debug.LogError("生成路径不存在！");
            }
        }
    }

    GameObject GetPoint(GameObject parent, string name)
    {
        GameObject point = new GameObject(name);
        point.transform.localPosition = Vector3.zero;
        point.transform.localScale = Vector3.one;
        point.transform.localRotation = Quaternion.Euler(Vector3.one);
        point.transform.SetParent(parent.transform);
        return point;
    }

    SimpleAnimation.EditorState GetState(AnimationClip clip, string name)
    {
        SimpleAnimation.EditorState s = new SimpleAnimation.EditorState();
        s.clip = clip;
        s.name = name;
        return s;
    }

    void LoadFBX()
    {
        if (GUILayout.Button("加载FBX"))
        {
            if (!string.IsNullOrEmpty(Path))
            {
                LoadFBXAuto();
            }
        }
    }

    void LoadFBXAuto()
    {
        DirectoryInfo direction = new DirectoryInfo(Path);
        FileInfo[] files = direction.GetFiles("*.fbx", SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            int startindex = files[i].FullName.IndexOf("Assets");
            string unityPath = files[i].FullName.Substring(startindex);
            if (!directoryPrefabs.Contains(unityPath))
            {
                directoryPrefabs.Add(unityPath);
            }
        }
    }
}
